package com.mxpio.erp.plm.service.impl;

import cn.hutool.core.util.StrUtil;
import com.mxpio.erp.common.plm.entity.*;
import com.mxpio.erp.common.plm.service.*;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.JpaUtil;
import com.mxpioframework.jpa.policy.CrudContext;
import com.mxpioframework.jpa.policy.impl.SmartCrudPolicyAdapter;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.security.annotation.Dict;
import com.mxpioframework.security.entity.User;
import com.mxpioframework.system.service.impl.BaseServiceImpl;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Column;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 项目任务模板Service业务层处理
 */
@Service
public class ProjectTaskTemplateServiceImpl extends BaseServiceImpl<ProjectTaskTemplate> implements ProjectTaskTemplateService {

    @Autowired
    private ProjectTaskDeliverableTemplateService projectTaskDeliverableTemplateService;

    @Autowired
    private ProjectTaskService projectTaskService;
    @Autowired
    private ProjectInfoTemplateService projectInfoTemplateService;


    @Override
    @Transactional
    public void changeTaskTemplate(ProjectInfoTemplate projectInfoTemplate) {
        List<ProjectTaskTemplate> proCode = this.list(ProjectTaskTemplate.class, Criteria.create().addCriterion("proCode", Operator.EQ, projectInfoTemplate.getProCode()));
        for (ProjectTaskTemplate projectTaskTemplate : proCode){
            projectTaskTemplate.setProName(projectInfoTemplate.getProName());
            projectTaskTemplate.setProLeader(projectInfoTemplate.getProLeader());
            projectTaskTemplate.setInfoDeptId(projectInfoTemplate.getInfoDeptId());
        }
    }

    /**
     *  删除项目任务模板信息，会同时删除对应的任务交付物模板
     * @param taskCode
     */
    @Override
    @Transactional
    public Result<?> deleteAll(String taskCode) {
        ProjectTaskTemplate byId = this.getById(ProjectTaskTemplate.class, taskCode);
        if(byId ==  null || StringUtils.isNotEmpty(byId.getAfterTask())){
            return Result.error("存在后置任务不允许删除！");
        }

        List<ProjectTaskTemplate> childrenTasks = this.getChildrenTasks(byId.getTemplateCode(), taskCode);
        List<String> taskCodes = childrenTasks.stream().map(ProjectTaskTemplate::getTaskCode).collect(Collectors.toList());
        taskCodes.add(taskCode);
        JpaUtil.lind(ProjectTaskTemplate.class).in("taskCode", taskCodes).delete();//删除任务
        JpaUtil.lind(ProjectTaskDeliverableTemplate.class).in("taskCode", taskCodes).delete();//删除任务交付物


        //删除任务模板
//        this.delete(ProjectTaskTemplate.class,taskCode);
        //删除对应的任务交付物模板
//        List<ProjectTaskDeliverableTemplate> taskDeliverableTemplate = projectTaskDeliverableTemplateService.list(ProjectTaskDeliverableTemplate.class, Criteria.create().addCriterion("taskCode", Operator.EQ, taskCode));
//        for (ProjectTaskDeliverableTemplate projectTaskDeliverableTemplate : taskDeliverableTemplate){
//            projectTaskDeliverableTemplateService.delete(ProjectTaskDeliverableTemplate.class,projectTaskDeliverableTemplate.getDocNO());
//        }
        return Result.OK("删除成功");
    }

    /**
     * 添加
     * @param taskTemplate
     * @return
     */
    @Override
    @Transactional
    public Result<?> saveAll(ProjectTaskTemplate taskTemplate) {

        List<ProjectInfoTemplate> projectInfoTemplates = projectInfoTemplateService.list(ProjectInfoTemplate.class, Criteria.create().addCriterion("templateCode", Operator.EQ, taskTemplate.getTemplateCode()));
        ProjectInfoTemplate projectInfoTemplate = projectInfoTemplates.get(0);
        taskTemplate.setInfoDeptId(projectInfoTemplate.getInfoDeptId());
//        //任务计划开始和计划结束时间不要再项目计划和结束之间
//        //获取任务模板的计划开始时间和计划结束时间
//        String templateCode = taskTemplate.getTemplateCode();
//        Date planStartTime = taskTemplate.getPlanStartTime();
//        Date planEndTime = taskTemplate.getPlanEndTime();
//        String proCode = taskTemplate.getProCode();
//        ProjectInfoTemplate one = JpaUtil.linq(ProjectInfoTemplate.class).equal("templateCode", templateCode).findOne();
//        //获取项目计划开始时间和项目计划结束时间
//        Date proPlanStartTime = one.getPlanStartTime();
//        Date proPlanEndTime = one.getPlanEndTime();
//        //判断任务计划开始时间和计划结束时间是否在项目计划和结束之间
//        if (planStartTime.before(proPlanStartTime) || planStartTime.after(proPlanEndTime) || planEndTime.before(proPlanStartTime) || planEndTime.after(proPlanEndTime)){
//            return Result.error("任务计划开始时间和计划结束时间必须在项目计划和结束时间之间" +"\n"+
//                    "项目计划开始时间："+proPlanStartTime+"\n" +
//                    "项目计划结束时间："+proPlanEndTime);
//        }
        if (StrUtil.isNotEmpty(taskTemplate.getParentTaskCode())){
            ProjectTaskTemplate parentTask = this.getById(ProjectTaskTemplate.class, taskTemplate.getParentTaskCode());
            taskTemplate.setParentTaskName(parentTask.getTaskName());
            taskTemplate.setParentHead(parentTask.getHead());
        }

        //确定当前任务层级
        int level = 0;
        if (StrUtil.isNotEmpty(taskTemplate.getParentTaskCode())){
            //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
            List<String> strings = new ArrayList<>();
            String parentTaskCode1 = taskTemplate.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode1,strings);
            level = rootTaskCodes.size();
            String strValue = Integer.toString(level);
            taskTemplate.setLevel(strValue+"级");
        }else {
            //如果当前任务没有父任务，则当前任务为根任务
            taskTemplate.setLevel("根任务");
        }

        this.save(taskTemplate,new SmartCrudPolicyAdapter(){
            @Override
            public boolean beforeInsert(CrudContext context) {
                Object o = context.getEntity();
                if (o instanceof ProjectTaskDeliverableTemplate){
                    ProjectTaskTemplate taskTemplate = context.getParent();
                    ((ProjectTaskDeliverableTemplate) o).setTaskCode(taskTemplate.getTaskCode());
                    ((ProjectTaskDeliverableTemplate) o).setTemplateCode(taskTemplate.getTemplateCode());
                }
                return true;
            }
        });


        return Result.OK(taskTemplate);
    }

    //取出当前任务的根任务
    private List<String> checkTask(String parentTaskCode, List<String> strings){
        //找到当前任务的父任务
        ProjectTaskTemplate parentTask = this.getById(ProjectTaskTemplate.class, parentTaskCode);
        //如果当前任务没有父任务，则当前任务为根任务
        if (StrUtil.isEmpty(parentTask.getParentTaskCode())){
            strings.add(parentTask.getTaskCode());
            return strings;
        }
        //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
        strings.add(parentTask.getTaskCode());
        String parentTaskCode1 = parentTask.getParentTaskCode();
        return checkTask(parentTaskCode1, strings);
    }

    /**
     * 更新
     * @param taskTemplate
     * @return
     */
    @Override
    @Transactional
    public Result<?> updateAll(ProjectTaskTemplate taskTemplate) {
//        //任务计划开始和计划结束时间不要再项目计划和结束之间
//        //获取任务模板的计划开始时间和计划结束时间
//        String templateCode = taskTemplate.getTemplateCode();
//        Date planStartTime = taskTemplate.getPlanStartTime();
//        Date planEndTime = taskTemplate.getPlanEndTime();
//        String proCode = taskTemplate.getProCode();
//        ProjectInfoTemplate one = JpaUtil.linq(ProjectInfoTemplate.class).equal("templateCode", templateCode).findOne();
//        //获取项目计划开始时间和项目计划结束时间
//        Date proPlanStartTime = one.getPlanStartTime();
//        Date proPlanEndTime = one.getPlanEndTime();
//        //判断任务计划开始时间和计划结束时间是否在项目计划和结束之间
//        if (planStartTime.before(proPlanStartTime) || planStartTime.after(proPlanEndTime) || planEndTime.before(proPlanStartTime) || planEndTime.after(proPlanEndTime)){
//            return Result.error("任务计划开始时间和计划结束时间必须在项目计划和结束时间之间" +"\n"+
//                    "项目计划开始时间："+proPlanStartTime+"\n" +
//                    "项目计划结束时间："+proPlanEndTime);
//        }

        //对父类子类，进行死循环检验
        ProjectTaskTemplate byId = this.getById(ProjectTaskTemplate.class, taskTemplate.getTaskCode());
        if(taskTemplate.getTaskCode().equals(taskTemplate.getParentTaskCode())){
            return Result.error("自己不能为自己的父级");
        }
        List<ProjectTaskTemplate> childrenTasks = this.getChildrenTasks(byId.getTemplateCode(), taskTemplate.getTaskCode());
        List<String> taskCodes = childrenTasks.stream().map(ProjectTaskTemplate::getTaskCode).collect(Collectors.toList());
        for (String taskCode : taskCodes){
            if (taskCode.equals(taskTemplate.getParentTaskCode())){
                return Result.error("子级不能为父级的父级");
            }
        }

        if (StrUtil.isNotEmpty(taskTemplate.getParentTaskCode())){
            ProjectTaskTemplate parentTask = this.getById(ProjectTaskTemplate.class, taskTemplate.getParentTaskCode());
            taskTemplate.setParentTaskName(parentTask.getTaskName());
            taskTemplate.setParentHead(parentTask.getHead());
        }

        //确定当前任务层级
        int level = 0;
        if (StrUtil.isNotEmpty(taskTemplate.getParentTaskCode())){
            //如果当前任务有父任务，则递归查找父任务的父任务，直到找到根任务
            List<String> strings = new ArrayList<>();
            String parentTaskCode1 = taskTemplate.getParentTaskCode();
            List<String> rootTaskCodes = checkTask(parentTaskCode1,strings);
            level = rootTaskCodes.size();
            String strValue = Integer.toString(level);
            taskTemplate.setLevel(strValue+"级");
        }else {
            //如果当前任务没有父任务，则当前任务为根任务
            taskTemplate.setLevel("根任务");
        }

        this.update(taskTemplate,new SmartCrudPolicyAdapter(){
            @Override
            public boolean beforeInsert(CrudContext context) {
                Object o = context.getEntity();
                if (o instanceof ProjectTaskDeliverableTemplate){
                    ProjectTaskTemplate taskTemplate = context.getParent();
                    ((ProjectTaskDeliverableTemplate) o).setTaskCode(taskTemplate.getTaskCode());
                    ((ProjectTaskDeliverableTemplate) o).setTemplateCode(taskTemplate.getTemplateCode());
                }
                return true;
            }
        });
        return Result.OK(taskTemplate);
    }


    /**
     * 获取所有子任务
     */
    public List<ProjectTaskTemplate> getChildrenTasks(String templateCode, String parentTaskCode) {
        // 获取当前项目下的所有任务
        List<ProjectTaskTemplate> allTasks = JpaUtil.linq(ProjectTaskTemplate.class).equal("templateCode", templateCode).list();

        // 初始化用于收集所有子任务的平铺列表
        List<ProjectTaskTemplate> flatChildrenList = new ArrayList<>();

        // 填充子任务列表
        findAllChildren(allTasks, parentTaskCode, flatChildrenList);

        return flatChildrenList;
    }

    /**
     * 递归辅助方法，用于收集所有子任务到平铺列表中
     */

    private void findAllChildren(List<ProjectTaskTemplate> allTasks, String parentTaskCode, List<ProjectTaskTemplate> flatChildrenList) {
        // 从所有任务中过滤出当前父任务代码下的直接子任务
        List<ProjectTaskTemplate> children = allTasks.stream().filter(task ->
                (StrUtil.isEmpty(parentTaskCode) ? StrUtil.isEmpty(task.getParentTaskCode()) : parentTaskCode.equals(task.getParentTaskCode()))
        ).collect(Collectors.toList());

        // 将找到的子任务添加到平铺列表中
        flatChildrenList.addAll(children);

        // 对每个找到的子任务递归寻找其子任务，并添加到平铺列表中
        for (ProjectTaskTemplate child : children) {
            findAllChildren(allTasks, child.getTaskCode(), flatChildrenList);
        }
    }
}
